Add script to generate Emacs builtin packages information
authorXiyue Deng <manphiz@gmail.com>
Tue, 17 Jun 2025 00:09:48 +0000 (17:09 -0700)
committerSean Whitton <spwhitton@spwhitton.name>
Fri, 25 Jul 2025 08:13:07 +0000 (09:13 +0100)
- Support output in human readable JSON format or as substvars

debian/generate-emacs-builtin-package-info.el [new file with mode: 0644]

diff --git a/debian/generate-emacs-builtin-package-info.el b/debian/generate-emacs-builtin-package-info.el
new file mode 100644 (file)
index 0000000..8292df5
--- /dev/null
@@ -0,0 +1,109 @@
+;; Emacs script to generate a package provide list -*- lexical-binding:t -*-
+(require 'json)
+(require 'package)
+
+(defvar package-skip-list
+  '("elpa-emacs")
+  "A list of package that should be skipped in the provide list")
+
+(defun package-version-list-to-string (package-version-list)
+  "Convert a package version list to version string acceptable in Debian."
+  (when package-version-list
+    (let ((count 0)
+          version-list)
+      (dolist (item package-version-list)
+        (progn
+          (if (< item 0)
+              (progn
+                ;; This roughly matches the mapping in
+                ;; version-regexp-alist.
+                (cl-case item
+                  (-1 (push "~rc" version-list))
+                  (-2 (push "~beta" version-list))
+                  (-3 (push "~alpha" version-list))
+                  (-4 (push "~snapshot" version-list))
+                  (t (error "Unknown version: %d" item)))
+                ;; no "." between prerelease name and number
+                (setq count 0))
+            (when (> count 0)
+              (push "." version-list))
+            (push (number-to-string item) version-list)
+            (cl-incf count))))
+      (string-join (nreverse version-list)))))
+
+(defun emacs-provided-package-versions ()
+  "Return an alist of Debian package name to version mapping."
+  (let (emacs-provided-package-versions)
+    (mapc (lambda (package-name)
+            (let* ((debian-package-name (concat "elpa-"
+                                                (symbol-name package-name)))
+                   (debian-package-version (package-version-list-to-string
+                                            (package-builtin-package-version
+                                             package-name))))
+              (when (not (member debian-package-name package-skip-list))
+                (push `(,debian-package-name . ,debian-package-version)
+                      emacs-provided-package-versions))))
+          (package-versioned-builtin-packages))
+    (sort emacs-provided-package-versions)))
+
+(defun print-help ()
+  "Print help info"
+  (message "Generate information for Emacs built-in packages.  Please use the following options:
+       --json          Generate a report in human readable JSON format
+       --substvars     Generate substvars for Emacs build process
+       --script-help   This help info
+"))
+
+(defun generate-builtin-package-info-json ()
+  "Generate Emacs built-in-package info report in JSON format."
+  (princ (format "%s\n"
+                 (with-temp-buffer
+                   (insert (json-encode (emacs-provided-package-versions)))
+                   (json-pretty-print-buffer)
+                   (buffer-string)))))
+
+(defun generate-builtin-package-info-substvars ()
+  "Generate Emacs built-in package info as substvars for emacs-common."
+  (let (provides-substvars-list
+        replaces-substvars-list
+        (count 0))
+    (mapc (lambda (package-version)
+            (let* ((name (car package-version))
+                   (version (cdr package-version))
+                   (provides-entry-string (concat name
+                                                  (when version
+                                                    (format " (= %s)" version))
+                                                  ","))
+                   (replaces-entry-string (concat name
+                                                  (when version
+                                                    (format " (<< %s)" version))
+                                                  ",")))
+              (when (> count 0)
+                (push " " provides-substvars-list)
+                (push " " replaces-substvars-list))
+              (push provides-entry-string provides-substvars-list)
+              (push replaces-entry-string replaces-substvars-list)
+              (cl-incf count)))
+          (emacs-provided-package-versions))
+    (let ((debian-provides-substvars-string
+           (string-join (nreverse provides-substvars-list)))
+          (debian-replaces-substvars-string
+           (string-join (nreverse replaces-substvars-list))))
+      (princ (format "emacs:Provides=%s\n" debian-provides-substvars-string))
+      (princ (format "emacs:Breaks=%s\n" debian-replaces-substvars-string))
+      (princ (format "emacs:Replaces=%s\n" debian-replaces-substvars-string)))))
+
+(defun main ()
+  "Main program entrance."
+  (if (not argv)
+      (print "Missing argument.  Should specify \"--report\" or \"--substvars\"."
+             #'external-debugging-output)
+    (let ((option (elt argv 0)))
+      (pcase option
+        ("--json" (generate-builtin-package-info-json))
+        ("--substvars" (generate-builtin-package-info-substvars))
+        ("--script-help" (print-help))
+        (_ (error "Unknown option \"%s\"." option)))))
+  (kill-emacs 0))
+
+(main)